package com.ruyuan2020.furnishing.account.service.impl;

import com.ruyuan2020.common.exception.BusinessException;
import com.ruyuan2020.furnishing.account.constant.AccountLogConstants;
import com.ruyuan2020.furnishing.account.constant.PointConstants;
import com.ruyuan2020.furnishing.account.dao.AccountDAO;
import com.ruyuan2020.furnishing.account.dao.AccountLogDAO;
import com.ruyuan2020.furnishing.account.domain.AccountDO;
import com.ruyuan2020.furnishing.account.domain.AccountDTO;
import com.ruyuan2020.furnishing.account.domain.GoldOperationRequestDTO;
import com.ruyuan2020.furnishing.account.domain.AccountLogDO;
import com.ruyuan2020.furnishing.account.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDAO accountDAO;

    @Autowired
    private AccountLogDAO accountLogDAO;

    /**
     * 创建账户信息
     *
     * @param accountDTO 账户信息
     */
    @Override
    @Transactional
    public void createAccount(AccountDTO accountDTO) {
        AccountDO accountDO = accountDTO.clone(AccountDO.class);
        accountDO.setGold(BigDecimal.ZERO);
        accountDO.setPoint(BigDecimal.ZERO);
        accountDAO.save(accountDO);
    }

    /**
     * 支付金币
     *
     * @param goldOperationRequestDTO 金币信息
     */
    @Override
    @Transactional
    public void payGold(GoldOperationRequestDTO goldOperationRequestDTO) {
        BigDecimal gold = accountDAO.getGoldById(goldOperationRequestDTO.getMemberId());
        if (gold.compareTo(goldOperationRequestDTO.getNumber()) >= 0) {
            accountDAO.subtractGold(goldOperationRequestDTO.getMemberId(), goldOperationRequestDTO.getNumber());
            saveLog(goldOperationRequestDTO.getMemberId(), goldOperationRequestDTO.getNumber().negate(), AccountLogConstants.TYPE_GOLD, goldOperationRequestDTO.getLog());
        } else throw new BusinessException("您的金币余额不足，请先充值");
    }

    /**
     * 添加金币
     *
     * @param goldOperationRequestDTO 金币信息
     */
    @Override
    @Transactional
    public void addGold(GoldOperationRequestDTO goldOperationRequestDTO) {
        // 支付金额和金币暂时是1:1
        BigDecimal newPoint = goldOperationRequestDTO.getNumber().multiply(PointConstants.POINT_RATE);
        accountDAO.addGoldAndPoint(goldOperationRequestDTO.getMemberId(), goldOperationRequestDTO.getNumber(), newPoint);
        saveLog(goldOperationRequestDTO.getMemberId(), goldOperationRequestDTO.getNumber(), AccountLogConstants.TYPE_GOLD, goldOperationRequestDTO.getLog());
        saveLog(goldOperationRequestDTO.getMemberId(), newPoint, AccountLogConstants.TYPE_POINT, goldOperationRequestDTO.getLog());
    }

    /**
     * 冻结金币
     *
     * @param goldOperationRequestDTO 金币信息
     */
    @Override
    @Transactional
    public void freezeGold(GoldOperationRequestDTO goldOperationRequestDTO) {
        BigDecimal gold = accountDAO.getGoldById(goldOperationRequestDTO.getMemberId());
        if (gold.compareTo(goldOperationRequestDTO.getNumber()) >= 0) {
            accountDAO.freezeGold(goldOperationRequestDTO.getMemberId(), goldOperationRequestDTO.getNumber());
        } else throw new BusinessException("您的金币余额不足，请先充值");
    }

    /**
     * 扣减冻结金币
     *
     * @param goldOperationRequestDTO 金币信息
     */
    @Override
    @Transactional
    public void payFreezeGold(GoldOperationRequestDTO goldOperationRequestDTO) {
        accountDAO.subtractFreezeGold(goldOperationRequestDTO.getMemberId(), goldOperationRequestDTO.getNumber());
        saveLog(goldOperationRequestDTO.getMemberId(), goldOperationRequestDTO.getNumber().negate(), AccountLogConstants.TYPE_GOLD, goldOperationRequestDTO.getLog());
    }

    /**
     * 保存日志
     *
     * @param memberId 会员id
     */
    private void saveLog(Long memberId, BigDecimal amount, String type, String log) {
        AccountLogDO accountLogDO = new AccountLogDO();
        accountLogDO.setMemberId(memberId);
        accountLogDO.setType(type);
        accountLogDO.setNumber(amount);
        accountLogDO.setLog(log);
        accountLogDAO.save(accountLogDO);
    }
}
